package com.ming_za.odupdaterserver.core.advice;

import com.ming_za.odupdaterserver.core.exception.BusinessException;
import com.ming_za.odupdaterserver.core.utils.Msg;
import com.ming_za.odupdaterserver.core.vo.R;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler implements ResponseBodyAdvice<Object> {

    private final Msg msg;

    public GlobalExceptionHandler(Msg msg) {
        this.msg = msg;
    }

    @ExceptionHandler(BusinessException.class)
    public R<?> error(BusinessException e) {
        msg.warn("[请求操作异常]" + e.getMsg());
        return R.error(e.getEType().getCode(), e.getMsg(),e.getData());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<?> error(MethodArgumentNotValidException e) {
        Map<String, String> map = new HashMap<>();
        for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
            map.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        return R.error(500,"参数错误",map);
    }

    @ExceptionHandler(NoResourceFoundException.class)
    public void error() {
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public R<?> error(MethodArgumentTypeMismatchException e) {
        return R.error(500,"参数异常",e.getMessage());
    }

    @ExceptionHandler(Throwable.class)
    public R<?> error(Throwable e) {
        msg.error("[全局异常]" + e.getMessage());
        e.printStackTrace();
        return R.error();
    }

    @ExceptionHandler(IOException.class)
    public R<?> error(IOException e) {
        msg.error("[IO异常]" + e.getMessage());
        return R.error();
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        if (body instanceof R<?> r){
            if (r.getCode() != 200){
                Msg.getInstance().warn("[" + request.getRemoteAddress().getHostString() + "]请求出错！原因：" + r.getMessage());
            }
        }

        return body;
    }
}
